package com.tongan.generate;

import com.tongan.entity.config.CgFormFieldEntity;
import com.tongan.entity.config.CgFormHeadEntity;
import com.tongan.entity.consts.TableConst;
import com.tongan.generate.tinyextend.MyCodeGenerator;
import com.tongan.generate.tinyextend.NewMetadata;
import com.tongan.generate.tinyextend.TemplateDefine;
import com.tongan.generate.tinyextend.TinyTemplateUtil;
import com.tongan.pojo.CreateFileProperty;
import com.tongan.pojo.GenerateEntity;
import com.tongan.pojo.onetomany.SubTableEntity;
import com.tongan.util.CodeDateUtils;
import com.tongan.util.CodeResourceUtil;
import com.tongan.util.NonceUtils;
import com.tongan.util.def.FtlDef;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.tinygroup.codegen.CodeGenerator;
import org.tinygroup.context.Context;
import org.tinygroup.vfs.FileObject;

import java.io.File;
import java.nio.file.Paths;
import java.util.*;

@Data
public class CgformCodeGenerate implements ICallBack {
   private static final Log log = LogFactory.getLog(CgformCodeGenerate.class);
   private String entityPackage = "test";
   private String sequenceCode = "";
   public static int FIELD_ROW_NUM = 1;
   private String cgformJspHtml;
   private SubTableEntity sub;
   private GenerateEntity subG;
   private CreateFileProperty subFileProperty;
   private String policy;
   private String[] array;
   private GenerateEntity cgformConfig;
   private TemplateEngineType engineType;
   /**
    * 根据前台配置的模版Metadata
    * 目前只实现哪些模版可以显示 哪些模版不显示
    */
   private NewMetadata configedMetadata;


   private static CreateFileProperty createFileProperty = new CreateFileProperty();

   static {
      createFileProperty.setActionFlag(true);
      createFileProperty.setServiceIFlag(true);
      createFileProperty.setJspFlag(true);
      createFileProperty.setServiceImplFlag(true);
      createFileProperty.setJspMode("01");
      createFileProperty.setPageFlag(true);
      createFileProperty.setEntityFlag(true);
   }

   public CgformCodeGenerate() {
   }

   public CgformCodeGenerate(CreateFileProperty createFileProperty2, GenerateEntity generateEntity,TemplateEngineType engineType) {
      FIELD_ROW_NUM = 1;
      createFileProperty = createFileProperty2;
      createFileProperty.setJspMode(createFileProperty2.getJspMode());
      this.sequenceCode = "";
      this.cgformConfig = generateEntity;
      this.engineType=engineType;
   }

   public CgformCodeGenerate(SubTableEntity sub, GenerateEntity subG, CreateFileProperty subFileProperty, String policy, String[] array) {
      createFileProperty = subFileProperty;
      FIELD_ROW_NUM = 1;
      this.sequenceCode = "";
      this.cgformConfig = subG;
      this.sub = sub;
      this.subG = subG;
      this.subFileProperty = subFileProperty;
      this.policy = policy;
   }

   public Map getFieldMeta(List<CgFormFieldEntity> columns){
      Map fieldMeta = new HashMap();
      Iterator var5 = columns.iterator();

      while(var5.hasNext()) {
         CgFormFieldEntity cf = (CgFormFieldEntity)var5.next();
         String type = cf.getType();
         if ("string".equalsIgnoreCase(type)) {
            cf.setType("java.lang.String");
         } else if ("Date".equalsIgnoreCase(type)) {
            cf.setType("java.util.Date");
         } else if ("double".equalsIgnoreCase(type)) {
            cf.setType("java.lang.Double");
         } else if ("int".equalsIgnoreCase(type)) {
            cf.setType("java.lang.Integer");
         } else if ("BigDecimal".equalsIgnoreCase(type)) {
            cf.setType("java.math.BigDecimal");
         } else if ("Text".equalsIgnoreCase(type)) {
            cf.setType("java.lang.String");
         } else if ("Blob".equalsIgnoreCase(type)) {
            cf.setType("java.sql.Blob");
         }else if ("Long".equalsIgnoreCase(type)){
            cf.setType("java.lang.Long");
         }else if ("Enum".equalsIgnoreCase(type)){
            cf.setType("Enum");
         }

         String fieldName = cf.getFieldName();
//         String fieldNameV = JeecgReadTable.formatField(fieldName);
//         cf.setFieldName(fieldNameV);
         fieldMeta.put(fieldName, fieldName);
      }
      return fieldMeta;
   }


   public Map execute() {
      Map data = new HashMap();

      data.put("controllerPrefix",cgformConfig.getControllerPrefix());
      data.put("uiPath",cgformConfig.getUiPath());
      //TODO 将包这个属性提取至GenerateEntity类 由代码生成页面提交 ,不要引用配置里面的
      data.put("bussiPackage", CodeResourceUtil.bussiPackage);
      data.put("bussiPackagePath", CodeResourceUtil.bussiPackage.replace(".","/"));
      data.put("entityPackage", this.entityPackage);
      //======= end
      //TODO 这几个属性提取至CgFormHeadEntity类做为数据库字段存储
      data.put("entityName", cgformConfig.getCgFormHead().getEntityName());
      data.put("lower_entityName",  cgformConfig.getCgFormHead().getVariableName());
      data.put("tableName", cgformConfig.getCgFormHead().getTableName());
      //======= end
      data.put("ftl_description", cgformConfig.getCgFormHead().getContent());
      data.put(FtlDef.JEECG_TABLE_ID, CodeResourceUtil.JEECG_GENERATE_TABLE_ID);
      data.put(FtlDef.JEECG_SEQUENCE_CODE, this.sequenceCode);
      data.put("ftl_create_time", CodeDateUtils.dateToString(new Date()));
      data.put(FtlDef.FIELD_REQUIRED_NAME, StringUtils.isNotEmpty(CodeResourceUtil.JEECG_UI_FIELD_REQUIRED_NUM) ? Integer.parseInt(CodeResourceUtil.JEECG_UI_FIELD_REQUIRED_NUM) : -1);
      data.put(FtlDef.SEARCH_FIELD_NUM, StringUtils.isNotEmpty(CodeResourceUtil.JEECG_UI_FIELD_SEARCH_NUM) ? Integer.parseInt(CodeResourceUtil.JEECG_UI_FIELD_SEARCH_NUM) : -1);
      data.put(FtlDef.FIELD_ROW_NAME, FIELD_ROW_NUM);

      try {
         List columns = this.cgformConfig.getCgFormHead().getColumns();


         List pageColumns = new ArrayList();
         Iterator var13 = columns.iterator();

         while(var13.hasNext()) {
            CgFormFieldEntity cf = (CgFormFieldEntity)var13.next();
            if (StringUtils.isNotEmpty(cf.getIsShow()) && "Y".equalsIgnoreCase(cf.getIsShow())) {
               pageColumns.add(cf);
            }
         }

         data.put("cgformConfig", this.cgformConfig);
         data.put("fieldMeta", getFieldMeta(columns));


         Map<String,Object> fieldM=new HashMap<>();
         //引用父字段列
         if (this.cgformConfig.getCgFormHead().getExtendCgFormHeadEntity()!=null){
            CgFormHeadEntity parent=this.cgformConfig.getCgFormHead().getExtendCgFormHeadEntity();
            do {
               if (parent!=null){
                  fieldM.putAll(getFieldMeta(parent.getColumns()));
                  parent=parent.getExtendCgFormHeadEntity();
               }
            }while (parent!=null);
            data.put("parent_fieldMeta", fieldM);
         }
         data.put("parent_fieldMeta",fieldM);
         columns.stream().sorted((s1,s2)->{
            return ((CgFormFieldEntity)s1).getOrderNum()>((CgFormFieldEntity)s2).getOrderNum()?1:2;
         }) ;

         //主键列
         columns.stream().filter(s->{
            return "Y".equals(((CgFormFieldEntity)s).getIsKey());
         }).findFirst().ifPresent(s->{data.put("keyCol",s);});


         data.put("columns", columns);
         data.put("table",cgformConfig.getCgFormHead());
         data.put("pageColumns", pageColumns);
         data.put("buttons", this.cgformConfig.getCgFormHead().getButtons());
         data.put("buttonSqlMap", this.cgformConfig.getButtonSqlMap() == null ? new HashMap(0) : this.cgformConfig.getButtonSqlMap());
         data.put("buttonJavaMap", this.cgformConfig.getButtonJavaMap() == null ? new HashMap(0) : this.cgformConfig.getButtonJavaMap());
         data.put("packageStyle", this.cgformConfig.getPackageStyle());
      } catch (Exception var9) {
         var9.printStackTrace();
      }

      long serialVersionUID = NonceUtils.randomLong() + NonceUtils.currentMills();
      data.put("serialVersionUID", String.valueOf(serialVersionUID));
      return data;
   }

   public void generateToFileUserDefined() throws Exception {
      log.info("----jeecg---Code----Generation----[单表模型:" + this.cgformConfig.getCgFormHead().getTableName() + "]------- 生成中。。。");

      String absolutePath= Paths.get(CgformCodeFactory.getClassPath(this.getClass()),CodeResourceUtil.FREEMARKER_CLASSPATH_USERDEFINED,createFileProperty.getJspMode()).toString();

      CgformCodeFactory codeFactory = new CgformCodeFactory();
      codeFactory.setProjectPath(this.cgformConfig.getProjectPath());
      codeFactory.setPackageStyle(this.cgformConfig.getPackageStyle());
      codeFactory.setEngineType(engineType);
      if (true){//this.cgformConfig.getCgFormHead().getJformType().intValue() == 1) {
         codeFactory.setCallBack(new CgformCodeGenerate(createFileProperty, this.cgformConfig,this.engineType));
      }

      String path = createFileProperty.getJspMode().replace(".", "/");
      log.info("----jeecg------path----[" + path + "]-------");
      if (engineType.equals(TemplateEngineType.Tiny)){
         File templateDataFile=Paths.get(absolutePath,"template.codegen.xml").toFile();

         if (templateDataFile.exists()){
            //tiny模版处理
            if (configedMetadata==null){
               configedMetadata= TinyTemplateUtil.findTemplateData(createFileProperty.getJspMode());
            }
            if (configedMetadata!=null){
               if (TableConst.JFORMTYPE_ManyToManyType.equals(cgformConfig.getCgFormHead().getJformType())){
                  //多对多不输出页面
                  configedMetadata.getTemplateDefines().forEach(s->{
                     if (s.getTemplatePath().endsWith("uipage")
                             ||s.getTemplatePath().contains("form")
                             ||s.getTemplatePath().contains("controller")){
                        s.setOutput(Boolean.FALSE);
                     }
                  });
               }
               //循环字段并输出模版
               codeFactory.setInterateOutput(output);
               codeFactory.setNewMetadata(configedMetadata);
               codeFactory.tinyTemplateGen(createFileProperty.getJspMode());
            }else{
               //模版文件不存在
            }
         }
      }
      log.info("----jeecg----Code----Generation-----[单表模型：" + this.cgformConfig.getCgFormHead().getTableName() + "]------ 生成完成。。。");
   }

   private MyCodeGenerator.InterateOutput output=new MyCodeGenerator.InterateOutput() {
      @Override
      public void prepare(CodeGenerator gener, Context newcontext, TemplateDefine templateDefine, FileObject templateFileObject) {
         //循环列
         if (CodeGenerateConsts.ITEM_COLUMNS.equalsIgnoreCase(templateDefine.getItems())) {
            String key=StringUtils.isNotBlank(templateDefine.getVar())? templateDefine.getVar():"col";
            List<CgFormFieldEntity> columns = cgformConfig.getCgFormHead().getColumns();
            columns.forEach(s -> {
               newcontext.put(key, s);
               try {
                  if (evaluteOutputable(gener,newcontext,templateDefine)) {
                     ((MyCodeGenerator) gener).outputFile(newcontext, templateFileObject, templateDefine);
                  }
               } catch (Exception e) {
                  log.error("输出模版错误",e);
               }
            });
         }
         //自定义按钮输出
         if (CodeGenerateConsts.ITEM_BUTTONS.equalsIgnoreCase(templateDefine.getItems())){
            String key=StringUtils.isNotBlank(templateDefine.getVar())? templateDefine.getVar():"btn";

            cgformConfig.getCgFormHead().getButtons().forEach(btn->{
               newcontext.put(key,btn);
               if (evaluteOutputable(gener,newcontext,templateDefine)){
                  try {
                     ((MyCodeGenerator)gener).outputFile(newcontext,templateFileObject,templateDefine);
                  }catch (Exception e){
                     log.error("输出模版错误",e);
                  }
               }
            });
         }
      }
   };

   /**
    * 根据当前模版的输出表达式判断是否需要输出
    * @param gener
    * @param newcontext
    * @param templateDefine
    * @return 默认true
    */
   public static boolean evaluteOutputable(CodeGenerator gener, Context newcontext, TemplateDefine templateDefine){
      boolean outputCurrent=true;
      String expression=templateDefine.getOutputableExpression();
      if (StringUtils.isNotBlank(expression)){
         String value=((MyCodeGenerator)gener).getGenerater().evaluteString(newcontext,expression);
         outputCurrent=Boolean.valueOf(value).booleanValue();
      }
      return outputCurrent;
   }
}
